package com.och.mrcp.service;

import com.och.mrcp.core.mrcp.model.MrcpEvent;
import com.och.mrcp.core.mrcp.model.MrcpMessage;
import com.och.mrcp.core.mrcp.model.MrcpRequest;
import com.och.mrcp.core.rtp.session.RtpSession;
import com.och.mrcp.handler.MrcpMessageSender;
import com.och.mrcp.config.EngineConfig;
import com.och.mrcp.model.SynthesisResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * SIP+MRCPv2语音合成集成服务
 * 整合SIP会话管理、MRCP消息处理和RTP音频推送
 */
@Slf4j
@Service
public class SipMrcpSynthesisService {
    
    private final Map<String, TtsSynthesisService> ttsProviders;
    private final MrcpMessageSender mrcpMessageSender;
    
    private final MediaSessionManager mediaSessionManager;
    
    public SipMrcpSynthesisService(
            List<TtsSynthesisService> ttsServices,
            MrcpMessageSender mrcpMessageSender,
            @Lazy MediaSessionManager mediaSessionManager) {
        this.mrcpMessageSender = mrcpMessageSender;
        this.mediaSessionManager = mediaSessionManager;
        Map<String, TtsSynthesisService> map = new HashMap<>();
        if (ttsServices != null) {
            for (TtsSynthesisService s : ttsServices) {
                try {
                    String name = s.getProviderName();
                    if (name != null && !name.trim().isEmpty()) {
                        map.put(name.toLowerCase(), s);
                    }
                } catch (Exception ignored) {}
            }
        }
        this.ttsProviders = Collections.unmodifiableMap(map);
    }
    
    // 活跃的合成会话：Call-ID -> SynthesisSession
    private final ConcurrentMap<String, SynthesisSession> synthesisSessions = new ConcurrentHashMap<>();
    
    /**
     * 处理SPEAK请求
     */
    public CompletableFuture<Void> handleSpeakRequest(String callId, MrcpRequest request, 
                                                     InetSocketAddress rtpAddress) {
        log.info("Processing SPEAK request for Call-ID: {}, RTP: {}:{}", 
                callId, rtpAddress.getAddress().getHostAddress(), rtpAddress.getPort());
        
        try {
            // 1. 提取要合成的文本
            String textToSynthesize = extractTextFromRequest(request);
            if (textToSynthesize == null || textToSynthesize.trim().isEmpty()) {
                log.error("No text to synthesize in request for Call-ID: {}", callId);
                sendSpeakFailedEvent(callId, request, "No text to synthesize");
                return CompletableFuture.failedFuture(new IllegalArgumentException("No text to synthesize"));
            }
            
            // 2. 创建合成配置
            EngineConfig.SynthesisConfig config = createSynthesisConfig(request);
            
            // 3. 创建合成会话
            SynthesisSession session = new SynthesisSession(callId, rtpAddress, request, config);
            synthesisSessions.put(callId, session);
            
            // 4. 开始语音合成（不发送SPEAK-START事件）
            return startSynthesis(callId, textToSynthesize, config)
                    .thenAccept(result -> {
                        try {
                            log.info("Synthesis completed for Call-ID: {}, duration: {}ms", 
                                    callId, result.getDuration());
                            
                            // 发送SPEAK-COMPLETE事件
                            sendSpeakCompleteEvent(callId, request, result);
                            
                            // 清理会话
                            synthesisSessions.remove(callId);
                            
                        } catch (Exception e) {
                            log.error("Error handling synthesis result for Call-ID: {}", callId, e);
                            sendSpeakFailedEvent(callId, request, "Error handling synthesis result");
                        }
                    })
                    .exceptionally(throwable -> {
                        log.error("Synthesis failed for Call-ID: {}", callId, throwable);
                        sendSpeakFailedEvent(callId, request, "Synthesis failed: " + throwable.getMessage());
                        synthesisSessions.remove(callId);
                        return null;
                    });
            
        } catch (Exception e) {
            log.error("Error processing SPEAK request for Call-ID: {}", callId, e);
            sendSpeakFailedEvent(callId, request, "Failed to process request: " + e.getMessage());
            return CompletableFuture.failedFuture(e);
        }
    }
    
    /**
     * 处理STOP请求
     */
    public void handleStopRequest(String callId, MrcpRequest request) {
        log.info("Processing STOP request for Call-ID: {}", callId);
        
        SynthesisSession session = synthesisSessions.get(callId);
        if (session != null) {
            // 停止合成
            session.stop();
            
            // 发送STOP-COMPLETE事件
            sendStopCompleteEvent(callId, request);
            
            // 清理会话
            synthesisSessions.remove(callId);
        } else {
            log.warn("No synthesis session found for Call-ID: {}", callId);
        }
    }
    
    /**
     * 处理PAUSE请求
     */
    public void handlePauseRequest(String callId, MrcpRequest request) {
        log.info("Processing PAUSE request for Call-ID: {}", callId);
        
        SynthesisSession session = synthesisSessions.get(callId);
        if (session != null) {
            session.pause();
            sendPauseCompleteEvent(callId, request);
        } else {
            log.warn("No synthesis session found for Call-ID: {}", callId);
        }
    }
    
    /**
     * 处理RESUME请求
     */
    public void handleResumeRequest(String callId, MrcpRequest request) {
        log.info("Processing RESUME request for Call-ID: {}", callId);
        
        SynthesisSession session = synthesisSessions.get(callId);
        if (session != null) {
            session.resume();
            sendResumeCompleteEvent(callId, request);
        } else {
            log.warn("No synthesis session found for Call-ID: {}", callId);
        }
    }
    
    /**
     * 开始语音合成
     */
    private CompletableFuture<SynthesisResult> startSynthesis(
            String callId, String text, EngineConfig.SynthesisConfig config) {
        
        SynthesisSession session = synthesisSessions.get(callId);
        if (session == null) {
            return CompletableFuture.failedFuture(new IllegalStateException("No synthesis session found"));
        }
        
        try {
            // 创建或获取RTP会话
            RtpSession rtpSession = createOrGetRtpSession(callId, session.getRtpAddress());
            session.setRtpSession(rtpSession);
            
            // 选择TTS提供商（优先请求头，其次默认）
            String provider = resolveTtsProvider(session.getRequest());
            TtsSynthesisService tts = ttsProviders.get(provider.toLowerCase());
            if (tts == null) {
                return CompletableFuture.failedFuture(new IllegalArgumentException("Unsupported TTS provider: " + provider));
            }
            if (!tts.isAvailable()) {
                return CompletableFuture.failedFuture(new IllegalStateException("TTS provider not available: " + provider));
            }
            if (rtpSession == null) {
                log.warn("No RTP session available for Call-ID: {}, synthesis will work but audio won't be sent via RTP", callId);
            }
            return tts.synthesize(callId, text, config, rtpSession);
            
        } catch (Exception e) {
            log.error("Failed to start synthesis for Call-ID: {}", callId, e);
            return CompletableFuture.failedFuture(e);
        }
    }
    
    /**
     * 创建或获取RTP会话
     */
    private RtpSession createOrGetRtpSession(String callId, InetSocketAddress clientAddress) {
        try {
            log.debug("Looking for existing RTP session for Call-ID: {}", callId);
            
            // 从MediaSessionManager获取现有的媒体会话
            MediaSessionManager.MediaSession mediaSession = mediaSessionManager.getMediaSession(callId);
            if (mediaSession != null) {
                RtpSession rtpSession = mediaSession.getRtpSession();
                if (rtpSession != null) {
                    log.info("Found existing RTP session for synthesis Call-ID: {}, session: {}", 
                            callId, rtpSession.getSessionId());
                    return rtpSession;
                } else {
                    log.warn("Media session exists but no RTP session for Call-ID: {}", callId);
                }
            } else {
                log.warn("No media session found for Call-ID: {}", callId);
            }
            
            // 如果没有找到现有的RTP会话，返回null
            // AliyunTtsSession会优雅地处理null RTP会话
            log.warn("No RTP session available for synthesis Call-ID: {}, audio will not be sent via RTP", callId);
            return null;
            
        } catch (Exception e) {
            log.error("Failed to get RTP session for Call-ID: {}", callId, e);
            return null; // 返回null而不是抛异常，让系统继续工作
        }
    }
    
    /**
     * 从MRCP请求中提取文本
     */
    private String extractTextFromRequest(MrcpRequest request) {
        // 从请求体中提取文本
        String body = request.getBody();
        if (body != null && !body.trim().isEmpty()) {
            // 简单的文本提取，实际应用中可能需要XML解析
            return body.trim();
        }
        
        // 从头部字段中查找文本
        String text = request.getHeaders().get("Content-Id");
        if (text != null && !text.trim().isEmpty()) {
            return text.trim();
        }
        
        return null;
    }
    
    /**
     * 创建合成配置
     */
    private EngineConfig.SynthesisConfig createSynthesisConfig(MrcpRequest request) {
        EngineConfig.SynthesisConfig config = new EngineConfig.SynthesisConfig();
        
        // 从MRCP请求头部获取配置参数
        String voice = request.getHeaders().get("Voice");
        if (voice != null) {
            config.setVoice(voice);
        }
        
        String language = request.getHeaders().get("Content-Language");
        if (language != null) {
            config.setLanguage(language);
        }
        
        String sampleRate = request.getHeaders().get("Sample-Rate");
        if (sampleRate != null) {
            try {
                config.setSampleRate(Integer.parseInt(sampleRate));
            } catch (NumberFormatException e) {
                log.warn("Invalid sample rate: {}, using default", sampleRate);
            }
        }
        
        return config;
    }
    
    /**
     * 解析TTS提供商
     * 优先从MRCP头部 Provider 或 Vendor 字段读取，否则使用 EngineConfig 默认
     */
    private String resolveTtsProvider(MrcpRequest request) {
        try {
            String header = request != null ? request.getHeaders().get("Provider") : null;
            if (header == null || header.isEmpty()) {
                header = request != null ? request.getHeaders().get("Vendor") : null;
            }
            if (header != null && !header.trim().isEmpty()) {
                return header.trim().toLowerCase();
            }
        } catch (Exception ignored) {}
        // fallback: 使用引擎默认提供商
        return "aliyun";
    }
    
    // 已不再使用：SPEAK-START事件在当前实现中不发送
    
    /**
     * 发送SPEAK-COMPLETE事件
     */
    private void sendSpeakCompleteEvent(String callId, MrcpRequest request, SynthesisResult result) {
        try {
            MrcpEvent event = new MrcpEvent(MrcpMessage.ResourceType.SPEECHSYNTH, MrcpEvent.EventType.SPEAK_COMPLETE);
            event.setMessageId(request.getMessageId());
            event.setSessionId(callId);
            // 使用请求中的Channel-Identifier保持一致性
            String channelId = request.getHeader("Channel-Identifier");
            if (channelId != null && !channelId.isEmpty()) {
                event.setChannelIdentifier(channelId);
            } else {
                event.setChannelIdentifier(callId);
            }
            // 完成状态
            event.setRequestState("COMPLETE");
            
            // 设置合成结果信息
            if (result != null) {
                event.getHeaders().put("Completion-Cause", "000 normal");
                event.getHeaders().put("Speech-Marker", String.valueOf(result.getDuration()));
            }
            
            mrcpMessageSender.sendMessage(callId, event);
            log.debug("Sent SPEAK-COMPLETE event for Call-ID: {}", callId);
            
        } catch (Exception e) {
            log.error("Error sending SPEAK-COMPLETE event for Call-ID: {}", callId, e);
        }
    }
    
    /**
     * 发送SPEAK-FAILED事件
     */
    private void sendSpeakFailedEvent(String callId, MrcpRequest request, String reason) {
        try {
            MrcpEvent event = new MrcpEvent(MrcpMessage.ResourceType.SPEECHSYNTH, MrcpEvent.EventType.SPEAK_FAILED);
            event.setMessageId(request.getMessageId());
            event.setSessionId(callId);
            event.setChannelIdentifier(callId);
            
            event.getHeaders().put("Completion-Cause", "001");
            event.getHeaders().put("Completion-Reason", reason);
            
            mrcpMessageSender.sendMessage(callId, event);
            log.debug("Sent SPEAK-FAILED event for Call-ID: {}", callId);
            
        } catch (Exception e) {
            log.error("Error sending SPEAK-FAILED event for Call-ID: {}", callId, e);
        }
    }
    
    /**
     * 发送STOP-COMPLETE事件
     */
    private void sendStopCompleteEvent(String callId, MrcpRequest request) {
        try {
            MrcpEvent event = new MrcpEvent(MrcpMessage.ResourceType.SPEECHSYNTH, MrcpEvent.EventType.SPEAK_COMPLETE);
            event.setMessageId(request.getMessageId());
            event.setSessionId(callId);
            event.setChannelIdentifier(callId);
            
            event.getHeaders().put("Completion-Cause", "002"); // Stopped
            
            mrcpMessageSender.sendMessage(callId, event);
            log.debug("Sent STOP-COMPLETE event for Call-ID: {}", callId);
            
        } catch (Exception e) {
            log.error("Error sending STOP-COMPLETE event for Call-ID: {}", callId, e);
        }
    }
    
    /**
     * 发送PAUSE-COMPLETE事件
     */
    private void sendPauseCompleteEvent(String callId, MrcpRequest request) {
        try {
            MrcpEvent event = new MrcpEvent(MrcpMessage.ResourceType.SPEECHSYNTH, MrcpEvent.EventType.SPEAK_COMPLETE);
            event.setMessageId(request.getMessageId());
            event.setSessionId(callId);
            event.setChannelIdentifier(callId);
            
            event.getHeaders().put("Completion-Cause", "003"); // Paused
            
            mrcpMessageSender.sendMessage(callId, event);
            log.debug("Sent PAUSE-COMPLETE event for Call-ID: {}", callId);
            
        } catch (Exception e) {
            log.error("Error sending PAUSE-COMPLETE event for Call-ID: {}", callId, e);
        }
    }
    
    /**
     * 发送RESUME-COMPLETE事件
     */
    private void sendResumeCompleteEvent(String callId, MrcpRequest request) {
        try {
            MrcpEvent event = new MrcpEvent(MrcpMessage.ResourceType.SPEECHSYNTH, MrcpEvent.EventType.SPEAK_COMPLETE);
            event.setMessageId(request.getMessageId());
            event.setSessionId(callId);
            event.setChannelIdentifier(callId);
            
            event.getHeaders().put("Completion-Cause", "004"); // Resumed
            
            mrcpMessageSender.sendMessage(callId, event);
            log.debug("Sent RESUME-COMPLETE event for Call-ID: {}", callId);
            
        } catch (Exception e) {
            log.error("Error sending RESUME-COMPLETE event for Call-ID: {}", callId, e);
        }
    }
    
    /**
     * 获取合成会话
     */
    public SynthesisSession getSynthesisSession(String callId) {
        return synthesisSessions.get(callId);
    }
    
    /**
     * 清理合成会话
     */
    public void cleanupSession(String callId) {
        SynthesisSession session = synthesisSessions.remove(callId);
        if (session != null) {
            session.stop();
            log.debug("Cleaned up synthesis session for Call-ID: {}", callId);
        }
    }
    
    /**
     * 合成会话状态
     */
    public enum SynthesisStatus {
        IDLE,       // 空闲状态
        SPEAKING,   // 正在合成
        PAUSED,     // 已暂停
        STOPPED     // 已停止
    }
    
    /**
     * 合成会话
     */
    public static class SynthesisSession {
        private final String callId;
        private final InetSocketAddress rtpAddress;
        private final MrcpRequest request;
        private final EngineConfig.SynthesisConfig config;
        private SynthesisStatus status = SynthesisStatus.IDLE;
        private RtpSession rtpSession;
        
        public SynthesisSession(String callId, InetSocketAddress rtpAddress, 
                              MrcpRequest request, EngineConfig.SynthesisConfig config) {
            this.callId = callId;
            this.rtpAddress = rtpAddress;
            this.request = request;
            this.config = config;
        }
        
        public void start() {
            status = SynthesisStatus.SPEAKING;
        }
        
        public void pause() {
            status = SynthesisStatus.PAUSED;
        }
        
        public void resume() {
            status = SynthesisStatus.SPEAKING;
        }
        
        public void stop() {
            status = SynthesisStatus.STOPPED;
        }
        
        // Getters
        public String getCallId() { return callId; }
        public InetSocketAddress getRtpAddress() { return rtpAddress; }
        public MrcpRequest getRequest() { return request; }
        public EngineConfig.SynthesisConfig getConfig() { return config; }
        public SynthesisStatus getStatus() { return status; }
        public RtpSession getRtpSession() { return rtpSession; }
        
        public void setRtpSession(RtpSession rtpSession) { this.rtpSession = rtpSession; }
    }
}
